/* Checksum: must be the negated sum of the first two fields. */
.long -0x1BADB004
+bad_cpu_msg:
+ .asciz "Bad CPU: does not support 64-bit (long) mode."
bad_cpu:
- jmp bad_cpu
+ mov $SYMBOL_NAME(bad_cpu_msg)-__PAGE_OFFSET,%esi
+ mov $0xB8000,%edi # VGA framebuffer
+1: mov (%esi),%bl
+ test %bl,%bl # Terminate on '\0' sentinel
+2: je 2b
+ mov $0x3f8+5,%dx # UART Line Status Register
+3: in %dx,%al
+ test $0x20,%al # Test THR Empty flag
+ je 3b
+ mov $0x3f8+0,%dx # UART Transmit Holding Register
+ mov %bl,%al
+ out %al,%dx # Send a character over the serial line
+ movsb # Write a character to the VGA framebuffer
+ mov $7,%al
+ stosb # Write an attribute to the VGA framebuffer
+ jmp 1b
__start:
- /* We begin by interrogating the CPU for the presence of long mode. */
- mov $0x80000000,%eax
- cpuid
- cmp $0x80000000,%eax # any function > 0x80000000?
- jbe bad_cpu
- mov $0x80000001,%eax
- cpuid
- bt $29,%edx # Long mode feature?
- jnc bad_cpu
-
/* Set up a few descriptors: on entry only CS is guaranteed good. */
lgdt %cs:nopaging_gdt_descr-__PAGE_OFFSET
mov $(__HYPERVISOR_DS),%ecx
pushl $0
popf
+ /* We begin by interrogating the CPU for the presence of long mode. */
+ mov $0x80000000,%eax
+ cpuid
+ cmp $0x80000000,%eax # any function > 0x80000000?
+ jbe bad_cpu
+ mov $0x80000001,%eax
+ cpuid
+ bt $29,%edx # Long mode feature?
+ jnc bad_cpu
+
/* Set up FPU. */
fninit
/* Initialise IDT with simple error defaults. */
lea ignore_int,%edx
- mov $(__HYPERVISOR_CS << 16),%eax
+ mov $(__HYPERVISOR_CS64 << 16),%eax
mov %dx,%ax /* selector = 0x0010 = cs */
mov $0x8E00,%dx /* interrupt gate - dpl=0, present */
lea SYMBOL_NAME(idt_table)-__PAGE_OFFSET,%edi
mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
mov %eax,%cr0
jmp 1f
+1: /* Now in compatibility mode. Long-jump into 64-bit mode. */
+ ljmp $(__HYPERVISOR_CS64),$1f
+
+ .code64
1: /* Install relocated selectors (FS/GS unused). */
lgdt gdt_descr
mov $(__HYPERVISOR_DS),%ecx
mov %ecx,%ds
mov %ecx,%es
mov %ecx,%ss
- ljmp $(__HYPERVISOR_CS),$1f
1: /* Paging enabled, so we can now enable GLOBAL mappings in CR4. */
- mov mmu_cr4_features,%ecx
- mov %ecx,%cr4
+ mov mmu_cr4_features,%rcx
+ mov %rcx,%cr4
/* Relocate ESP */
add $__PAGE_OFFSET,%esp
/* This is the default interrupt handler. */
int_msg:
.asciz "Unknown interrupt\n"
- ALIGN
ignore_int:
cld
mov $(__HYPERVISOR_DS),%eax
mov %eax,%ds
mov %eax,%es
- pushl $int_msg
+ pushq $int_msg
call SYMBOL_NAME(printf)
1: jmp 1b
+ .code32
+ .align 8
+
/*** STACK LOCATION ***/
ENTRY(stack_start)
.globl SYMBOL_NAME(idt)
.globl SYMBOL_NAME(gdt)
- ALIGN
-
.word 0
idt_descr:
.word 256*8-1